import { Player, Position, BOARD_SIZE, DIRECTIONS } from '../types/game';

// 棋型定义
interface Pattern {
  name: string;
  description: string;
  score: number;
  isWinning: boolean;
}

// 开局库
const OPENING_BOOK: Position[] = [
  { row: 7, col: 7 }, // 中心点
  { row: 7, col: 6 }, // 右中心
  { row: 7, col: 8 }, // 右中心
  { row: 6, col: 7 }, // 上中心
  { row: 8, col: 7 }, // 下中心
];

// 位置权重（中心位置更重要）
const getPositionWeight = (row: number, col: number): number => {
  const center = Math.floor(BOARD_SIZE / 2);
  const distanceFromCenter = Math.abs(row - center) + Math.abs(col - center);
  const maxDistance = center * 2;
  return maxDistance - distanceFromCenter;
};

// 棋型评估表
const PATTERNS: Pattern[] = [
  { name: 'FIVE', description: '五子连珠', score: 100000, isWinning: true },
  { name: 'OPEN_FOUR', description: '活四', score: 50000, isWinning: false },
  { name: 'BLOCKED_FOUR', description: '冲四', score: 5000, isWinning: false },
  { name: 'OPEN_THREE', description: '活三', score: 5000, isWinning: false },
  { name: 'BLOCKED_THREE', description: '眠三', score: 500, isWinning: false },
  { name: 'OPEN_TWO', description: '活二', score: 500, isWinning: false },
  { name: 'BLOCKED_TWO', description: '眠二', score: 50, isWinning: false },
  { name: 'SINGLE', description: '单子', score: 10, isWinning: false },
];

// 检查五子连珠
const checkFiveInRow = (board: Player[][], row: number, col: number, player: Player): Position[] => {
  for (const { dr, dc } of DIRECTIONS) {
    const line: Position[] = [{ row, col }];
    
    // 正方向检查
    for (let i = 1; i < 5; i++) {
      const newRow = row + dr * i;
      const newCol = col + dc * i;
      if (newRow >= 0 && newRow < BOARD_SIZE && newCol >= 0 && newCol < BOARD_SIZE && 
          board[newRow][newCol] === player) {
        line.push({ row: newRow, col: newCol });
      } else {
        break;
      }
    }
    
    // 反方向检查
    for (let i = 1; i < 5; i++) {
      const newRow = row - dr * i;
      const newCol = col - dc * i;
      if (newRow >= 0 && newRow < BOARD_SIZE && newCol >= 0 && newCol < BOARD_SIZE && 
          board[newRow][newCol] === player) {
        line.unshift({ row: newRow, col: newCol });
      } else {
        break;
      }
    }
    
    if (line.length >= 5) {
      return line.slice(0, 5);
    }
  }
  
  return [];
};

// 检查特定棋型
const checkPattern = (line: (Player | null)[], player: Player): Pattern | null => {
  const playerCount = line.filter(cell => cell === player).length;
  const emptyCount = line.filter(cell => cell === null).length;
  const opponentCount = line.filter(cell => cell && cell !== player).length;
  
  if (opponentCount > 0) return null;
  
  if (playerCount === 5) {
    return PATTERNS.find(p => p.name === 'FIVE')!;
  }
  
  if (playerCount === 4) {
    if (emptyCount === 1) {
      return PATTERNS.find(p => p.name === 'OPEN_FOUR')!;
    } else if (emptyCount === 0) {
      return PATTERNS.find(p => p.name === 'BLOCKED_FOUR')!;
    }
  }
  
  if (playerCount === 3) {
    if (emptyCount === 2) {
      return PATTERNS.find(p => p.name === 'OPEN_THREE')!;
    } else if (emptyCount === 1) {
      return PATTERNS.find(p => p.name === 'BLOCKED_THREE')!;
    }
  }
  
  if (playerCount === 2) {
    if (emptyCount === 3) {
      return PATTERNS.find(p => p.name === 'OPEN_TWO')!;
    } else if (emptyCount === 2) {
      return PATTERNS.find(p => p.name === 'BLOCKED_TWO')!;
    }
  }
  
  if (playerCount === 1 && emptyCount === 4) {
    return PATTERNS.find(p => p.name === 'SINGLE')!;
  }
  
  return null;
};

// 获取某个方向的线段
const getLineFromPosition = (
  board: Player[][], 
  row: number, 
  col: number, 
  dr: number, 
  dc: number, 
  length: number = 9
): (Player | null)[] => {
  const line: (Player | null)[] = [];
  const startRow = row - Math.floor(length / 2) * dr;
  const startCol = col - Math.floor(length / 2) * dc;
  
  for (let i = 0; i < length; i++) {
    const newRow = startRow + i * dr;
    const newCol = startCol + i * dc;
    
    if (newRow >= 0 && newRow < BOARD_SIZE && newCol >= 0 && newCol < BOARD_SIZE) {
      line.push(board[newRow][newCol]);
    } else {
      line.push(null);
    }
  }
  
  return line;
};

// 评估单个位置的强度
const evaluatePosition = (board: Player[][], row: number, col: number, player: Player): number => {
  if (board[row][col] !== null) return 0;
  
  let totalScore = 0;
  
  // 检查每个方向
  for (const { dr, dc } of DIRECTIONS) {
    const line = getLineFromPosition(board, row, col, dr, dc, 9);
    const pattern = checkPattern(line, player);
    
    if (pattern) {
      totalScore += pattern.score;
    }
  }
  
  // 位置权重
  totalScore += getPositionWeight(row, col);
  
  return totalScore;
};

// 检查是否已经获胜
const checkImmediateWin = (board: Player[][], row: number, col: number, player: Player): boolean => {
  const winningLine = checkFiveInRow(board, row, col, player);
  return winningLine.length > 0;
};

// 检查对手是否即将获胜（需要阻挡）
const checkImmediateThreat = (board: Player[][], row: number, col: number, player: Player): number => {
  const opponent = player === 'black' ? 'white' : 'black';
  let threatLevel = 0;
  
  // 检查每个方向是否形成威胁
  for (const { dr, dc } of DIRECTIONS) {
    const line = getLineFromPosition(board, row, col, dr, dc, 9);
    const pattern = checkPattern(line, opponent);
    
    if (pattern && (pattern.name === 'OPEN_FOUR' || pattern.name === 'OPEN_THREE')) {
      threatLevel = Math.max(threatLevel, pattern.score);
    }
  }
  
  return threatLevel;
};

// 获取候选移动位置（只在棋子附近搜索，减少搜索空间）
const getCandidateMoves = (board: Player[][]): Position[] => {
  const candidates: Position[] = [];
  const visited = new Set<string>();
  
  // 收集已有棋子周围的空位
  for (let row = 0; row < BOARD_SIZE; row++) {
    for (let col = 0; col < BOARD_SIZE; col++) {
      if (board[row][col] !== null) {
        // 在已有棋子周围2格范围内搜索
        for (let dr = -2; dr <= 2; dr++) {
          for (let dc = -2; dc <= 2; dc++) {
            const newRow = row + dr;
            const newCol = col + dc;
            const key = `${newRow}-${newCol}`;
            
            if (newRow >= 0 && newRow < BOARD_SIZE && 
                newCol >= 0 && newCol < BOARD_SIZE && 
                board[newRow][newCol] === null && 
                !visited.has(key)) {
              candidates.push({ row: newRow, col: newCol });
              visited.add(key);
            }
          }
        }
      }
    }
  }
  
  // 如果棋盘为空，返回开局库
  if (candidates.length === 0) {
    return OPENING_BOOK;
  }
  
  return candidates;
};

// 改进的Minimax算法
const minimaxWithAlphaBeta = (
  board: Player[][],
  depth: number,
  alpha: number,
  beta: number,
  isMaximizing: boolean,
  player: Player
): { score: number; position?: Position } => {
  const opponent = player === 'black' ? 'white' : 'black';
  
  // 检查游戏结束状态
  for (let row = 0; row < BOARD_SIZE; row++) {
    for (let col = 0; col < BOARD_SIZE; col++) {
      if (board[row][col] === player && checkImmediateWin(board, row, col, player)) {
        return { score: 100000 };
      }
      if (board[row][col] === opponent && checkImmediateWin(board, row, col, opponent)) {
        return { score: -100000 };
      }
    }
  }
  
  if (depth === 0) {
    return { score: evaluateBoardAdvanced(board, player) };
  }
  
  const candidates = getCandidateMoves(board);
  
  if (isMaximizing) {
    let maxScore = -Infinity;
    let bestPosition: Position | undefined;
    
    for (const move of candidates) {
      const newBoard = [...board];
      newBoard[move.row] = [...newBoard[move.row]];
      newBoard[move.row][move.col] = player;
      
      const result = minimaxWithAlphaBeta(newBoard, depth - 1, alpha, beta, false, player);
      
      if (result.score > maxScore) {
        maxScore = result.score;
        bestPosition = move;
      }
      
      alpha = Math.max(alpha, result.score);
      if (beta <= alpha) break; // Alpha-beta剪枝
    }
    
    return { score: maxScore, position: bestPosition };
  } else {
    let minScore = Infinity;
    let bestPosition: Position | undefined;
    
    for (const move of candidates) {
      const newBoard = [...board];
      newBoard[move.row] = [...newBoard[move.row]];
      newBoard[move.row][move.col] = opponent;
      
      const result = minimaxWithAlphaBeta(newBoard, depth - 1, alpha, beta, true, player);
      
      if (result.score < minScore) {
        minScore = result.score;
        bestPosition = move;
      }
      
      beta = Math.min(beta, result.score);
      if (beta <= alpha) break; // Alpha-beta剪枝
    }
    
    return { score: minScore, position: bestPosition };
  }
};

// 高级棋盘评估
const evaluateBoardAdvanced = (board: Player[][], player: Player): number => {
  let totalScore = 0;
  const opponent = player === 'black' ? 'white' : 'black';
  
  // 检查所有位置
  for (let row = 0; row < BOARD_SIZE; row++) {
    for (let col = 0; col < BOARD_SIZE; col++) {
      if (board[row][col] === player) {
        totalScore += evaluatePosition(board, row, col, player);
      } else if (board[row][col] === opponent) {
        totalScore -= evaluatePosition(board, row, col, opponent);
      }
    }
  }
  
  return totalScore;
};

// AI获取最佳移动
export const getAdvancedAIMove = (board: Player[][], aiPlayer: Player, difficulty: number = 4): Position | null => {
  // 检查第一步
  const emptyCount = board.flat().filter(cell => cell === null).length;
  if (emptyCount === BOARD_SIZE * BOARD_SIZE) {
    return OPENING_BOOK[0]; // 第一步下中心
  }
  
  if (emptyCount === BOARD_SIZE * BOARD_SIZE - 1) {
    return OPENING_BOOK[0]; // 第二步也下中心附近
  }
  
  // 检查是否能立即获胜
  for (let row = 0; row < BOARD_SIZE; row++) {
    for (let col = 0; col < BOARD_SIZE; col++) {
      if (board[row][col] === null && checkImmediateWin(board, row, col, aiPlayer)) {
        return { row, col };
      }
    }
  }
  
  // 检查是否需要阻挡对手获胜
  const opponent = aiPlayer === 'black' ? 'white' : 'black';
  let bestDefensiveMove: Position | null = null;
  let maxThreat = 0;
  
  for (let row = 0; row < BOARD_SIZE; row++) {
    for (let col = 0; col < BOARD_SIZE; col++) {
      if (board[row][col] === null) {
        const threat = checkImmediateThreat(board, row, col, aiPlayer);
        if (threat > maxThreat) {
          maxThreat = threat;
          bestDefensiveMove = { row, col };
        }
      }
    }
  }
  
  // 如果对手即将获胜，必须阻挡
  if (maxThreat > 40000) {
    return bestDefensiveMove;
  }
  
  // 使用改进的Minimax算法
  const result = minimaxWithAlphaBeta(board, difficulty, -Infinity, Infinity, true, aiPlayer);
  
  return result.position || bestDefensiveMove || { row: 7, col: 7 };
};